package cn.tansanqinger.controller.chatroom;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;

import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;

import cn.tansanqinger.dao.sql.chatroom.ChatMessageSqlDaoImpl;
import cn.tansanqinger.pojo.Chatmessage;
import cn.tansanqinger.pojo.Friendlist;
import cn.tansanqinger.service.chatroom.IFriendlistService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
@RequiredArgsConstructor
@Controller
@Component
public class MsgSendService {

    private static final Map<String, SocketIOClient> CLIENT_MAP = new ConcurrentHashMap<>();
    private static final List<Chatmessage> CHATMESSAGES = new ArrayList<Chatmessage>(500);
    private static final List<Chatmessage> SELECTCHATEMSSAGE = new ArrayList<Chatmessage>();
    private static final Map<String, Integer> SELECTCHATNUMBER = new HashMap<String, Integer>();
    private final SocketIOServer socketIOServer;
    
    
    @Autowired
    private IFriendlistService fservice;
    @Autowired
    private ChatMessageSqlDaoImpl impl;
    

    /**
     * 启动的时候会被调用一次
     */
    @PostConstruct
    private void autoStart() {
        socketIOServer.addConnectListener(client -> {
        	String userphone = client.getHandshakeData().getSingleUrlParam("userAccount");
            if(userphone.matches("\\d+")&&userphone.length()==10) {
            	CLIENT_MAP.put(userphone, client);
            	//通知好友已经上线
            	notifyFriendsLine(userphone,0);
            }
        });
        socketIOServer.addDisconnectListener(client -> {
        	//通知好友 他已经下线了
        	String userphone = client.getHandshakeData().getSingleUrlParam("userAccount");
            CLIENT_MAP.remove(userphone);
            notifyFriendsLine(userphone,1);
            client.disconnect();
        });
        socketIOServer.start();
    }

    @PreDestroy
    private void onDestroy() {
        if (socketIOServer != null) {
            socketIOServer.stop();
        }
    }
    
    //通知好友
    public void notifyFriendsLine(String account , int line) {
    	List<Friendlist> friendlists = fservice.selectAccountMessage(account);
    	if(!friendlists.isEmpty()) {
    		for (int j = 0; j < friendlists.size(); j++) {
	    		Map<String,Object> map=new HashMap<>();
	    		map.put("account", account);
	    		if(line == 0) {
	    			map.put("code", 300);
	    			map.put("msg", friendlists.get(j).getFcomment()+"上线了");
	    		} else {
	    			map.put("msg", friendlists.get(j).getFcomment()+"下线了");
	    		}
	    		sendMsg(map, friendlists.get(j).getUaccount(), "notifyFriendsLine");
    		}
    	}
    	
    }
    
    //发送消息
    public int sendMsg(Map<String, Object> demo,String sname, String type) {
        CLIENT_MAP.forEach((key, value) -> {
        	System.err.println(sname);
        	if(key.equals(sname)) {
	            value.sendEvent(type, demo);
	            log.info("发送数据成功:{}", key);
        	} 
        });
        return CLIENT_MAP.size();
    }
    
    
    //每十分种写入一次数据
    @Scheduled(fixedDelay = 10 * 60 * 1000)
    public void addChatMessage() {
    	if(!CHATMESSAGES.isEmpty()) {
    		impl.add(CHATMESSAGES);
    		CHATMESSAGES.clear();
    		SELECTCHATEMSSAGE.clear();
    		SELECTCHATNUMBER.clear();
    	}
    }
    
    //删除过时的数据
    @Scheduled(fixedDelay = 10 * 60 * 1000)
    public void deleteChatMessage() {
    	impl.delete(System.currentTimeMillis()/1000-7*24*60*60);
    }
    
    //进行数据存储操作
    public void chatMessageSave(Chatmessage chatmessage) {
    	chatmessage.setIsread(null!=CLIENT_MAP.get(chatmessage.getSaccount()));
    	CHATMESSAGES.add(chatmessage);
    	if(CHATMESSAGES.size()==500) {
    		//进行数据保存
    		impl.add(CHATMESSAGES);
    		CHATMESSAGES.clear();
    		SELECTCHATEMSSAGE.clear();
    		SELECTCHATNUMBER.clear();
    	}
    }

    //查询数据
	public List<Chatmessage> beforeChatMessage(String sname, String fname) {
		List<Chatmessage> chatmessages = new ArrayList<Chatmessage>();
		for (int i = 0; i < CHATMESSAGES.size(); i++) {
			if((sname.equals(CHATMESSAGES.get(i).getFaccount())&&fname.equals(CHATMESSAGES.get(i).getSaccount()))||
					(fname.equals(CHATMESSAGES.get(i).getFaccount())&&sname.equals(CHATMESSAGES.get(i).getSaccount()))) {
				chatmessages.add(CHATMESSAGES.get(i));
			}
		}
		if(chatmessages.isEmpty()) {
			for (int j = 0; j < SELECTCHATEMSSAGE.size(); j++) {
				if((sname.equals(SELECTCHATEMSSAGE.get(j).getFaccount())&&fname.equals(SELECTCHATEMSSAGE.get(j).getSaccount()))||
						(fname.equals(SELECTCHATEMSSAGE.get(j).getFaccount())&&sname.equals(SELECTCHATEMSSAGE.get(j).getSaccount()))) {
					chatmessages.add(SELECTCHATEMSSAGE.get(j));
				}
			}
		}
		if(chatmessages.isEmpty()) {
			Integer number = SELECTCHATNUMBER.get(sname+fname);
			if(number==null) {//判断是否有数据
				number = SELECTCHATNUMBER.get(sname+fname);
			}
			//还未查询过数据，需要进行数据查询
			chatmessages = impl.selectChatmessages(sname, fname, 1);
			SELECTCHATNUMBER.put(sname+fname, chatmessages.size());
			if(!chatmessages.isEmpty()) {
				for (int i = 0; i < chatmessages.size(); i++) {
					SELECTCHATEMSSAGE.add(chatmessages.get(i));
				}
			}
		}
		return chatmessages;
	}
}
